package br.ufla.pgcc.oomeasures.astvisitors;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclaration;

public class MethodLinesOfCodeVisitor extends ASTVisitor {
	private static Map<String, Integer> linesPerMethod = new HashMap<String, Integer>();

	@Override
	public boolean visit(MethodDeclaration method) {
		countLinesOfCode(method);

		return super.visit(method);
	}

	private void countLinesOfCode(MethodDeclaration method){

		// remove o Javadoc para contar apenas o numero de linhas de codigo 
		Javadoc javadoc = method.getJavadoc();
		if (javadoc != null) {
			javadoc.delete();
		}
		String methodName = getMethodNameWithParameters(method);
		int numberOfLines = method.toString().split("\n").length;
		linesPerMethod.put(methodName, numberOfLines);
	}
	
	public int getNumberOfLinesOfCode(IMethod method){
		String methodName = getMethodNameWithParameters(method);
		if (!linesPerMethod.containsKey(methodName)) {
			return 0;
		}
		return linesPerMethod.get(methodName);
	}
	
	public static String getMethodNameWithParameters(IMethod method){
		String methodName = method.getElementName();
		String[] parametersType = method.getParameterTypes();

		StringBuilder signature = new StringBuilder();
		signature.append(methodName);
		signature.append("(");

		for (String parameterType : parametersType) {
			signature.append(Signature.getSignatureSimpleName(parameterType));
			signature.append(", ");
		}

		// removendo a ultima virgula e seu respectivo espaco
		if (signature.lastIndexOf(",") > 0) {
			signature.replace(signature.lastIndexOf(","), signature.length(), "");
		}
		signature.append(")");

		return signature.toString();
	}
	
	private String getMethodNameWithParameters(MethodDeclaration method){
		StringBuilder signature = new StringBuilder();
		signature.append(method.getName());
		signature.append("(");
		
		for (Object parameter : method.parameters()) {
            VariableDeclaration variableDeclaration = (VariableDeclaration) parameter;
            String type = variableDeclaration.getStructuralProperty(SingleVariableDeclaration.TYPE_PROPERTY)
                    .toString();
            for (int i = 0; i < variableDeclaration.getExtraDimensions(); i++) {
                type += "[]";
            }
            signature.append(type);
			signature.append(", ");

        }
		// removendo a ultima virgula e seu respectivo espaco
		if (signature.lastIndexOf(",") > 0) {
			signature.replace(signature.lastIndexOf(","), signature.length(), "");
		}
		signature.append(")");
		
		return signature.toString();
	} 
	
} 
